import { compileToFunction } from "./compiler/index";
import { mountComponent } from "./lifecycle";
import { initState } from "./state";
import { mergeOptions, nextTick } from "./utils";

export function initMixin(Vue) {

  Vue.prototype._init = function (options) {

    const vm = this;
    // 老的 直接把options添加到实例vm上：vm.$options = options; //把用户选项放到vm上，这样在其他方法上都可以获取到options

    //新的： 把options和全全局的options合并后添加到vm实例上 ：对生命周期和components，有额外的处理规则
    vm.$options = mergeOptions(vm.constructor.options, options);// 初始化实例时，将传入和options和Vue上的options合并，后续如果使用Vue.minix在继续将传入的options和全局的options合并

    initState(vm)

    // 模板编译

    // 1.挂载
    if (vm.$options.el) {
      // 现在数据已经被劫持了，数据变化需要更新视图，diff算法更新需要更新的部分
      vm.$mount(vm.$options.el)
    }

  }
  // new Vue({el:xx})  new Vue().$mount
  Vue.prototype.$mount = function (el) {
    const vm = this;
    const opts = vm.$options;
    // 
    el = document.querySelector(el) // 获取挂载的真实元素
    vm.$el = el;

    // 编译优先级 render >template>el.outerHTML
    if (!opts.render) {
      let template = opts.template;
      if (!template) {
        template = el.outerHTML;
      }
      let render = compileToFunction(template);
      opts.render = render;
    }
    mountComponent(vm)
  }
  Vue.prototype.$nextTick = nextTick
}